﻿// -----------------------------------------------------------------------
//  <copyright file="OnlineUserProvider.cs" company="LiuliuSoft">
//      Copyright (c) 2025 66SOFT. All rights reserved.
//  </copyright>
//  <site>https://ifs.66soft.net</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-09-27 18:09</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Domain;
using DaprPlus.Extensions;
using DaprPlus.Identity;

using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;

using OSharp.Caching;


namespace DaprPlus.Dapr;

public class OnlineUserProvider(IServiceProvider provider) : IOnlineUserProvider
{
    private readonly IDistributedCache _cache = provider.GetRequiredService<IDistributedCache>();

    public async Task<OnlineUser?> GetAsync()
    {
        var userName = GetCurrentUserName();
        if (string.IsNullOrEmpty(userName))
        {
            return null;
        }
        var key = GetKey(userName);
        return await _cache.GetAsync(key, async () =>
        {
            //缓存不存在时，调用认证服务器获取（并重建）在线用户信息
            var options = provider.GetOptions<DaprOptions>();
            if (options == null || !options.AppIds.TryGetValue("Identity", out var identityAppId))
            {
                return null;
            }

            var daprClient = provider.GetRequiredService<DaprClient>();
            var request = provider.CreateInvokeMethodRequest(HttpMethod.Get, identityAppId, "/api/identity/online");
            var result = await daprClient.InvokeMethodAsync<ApiResult<OnlineUser>>(request);
            return !result.IsSuccess() ? null : result.Data;
        });
    }

    public async Task RemoveAsync(string? userName = null)
    {
        userName ??= GetCurrentUserName();
        if (string.IsNullOrEmpty(userName))
        {
            return;
        }
        var key = GetKey(userName);
        await _cache.RemoveAsync(key);
    }

    private static string GetKey(string userName)
    {
        return $"Share:OnlineUser:{userName}";
    }

    private string? GetCurrentUserName()
    {
        var principal = provider.GetCurrentUser();
        if (principal is not { Identity.IsAuthenticated: true })
        {
            return null;
        }
        var userName = principal.Identity.Name!;
        return userName;
    }
}